#include "optparse.h"
#include "error.h"
#include <unistd.h>
#include <getopt.h>
#include <string.h>

struct cconf_optlist_s {
	struct option * opts;
	int n_opts;
	cconf_opt_handler_fcn_t handler_fcn;
	void * data;
};

cconf_optlist_t * cconf_optlist_create(cconf_opt_handler_fcn_t fcn, void * handler_data)
{
	cconf_optlist_t * o = calloc(1, sizeof(cconf_optlist_t));
	
	o->opts = NULL;
	o->n_opts = 0;
	
	o->handler_fcn = fcn;
	o->data = handler_data;

	return o;
}

void cconf_optlist_free(cconf_optlist_t * o)
{
	free(o->opts);
	free(o);
}

int cconf_optlist_append(cconf_optlist_t * o, char * name, int has_arg, int val)
{
	o->opts = realloc(o->opts, (o->n_opts + 2) * sizeof(struct option));
    
    if (!o->opts)
		return CCONF_ERROR_NOMEM;
		
    memset(o->opts + o->n_opts, 0, 2 * sizeof(struct option));
    
    o->opts[o->n_opts].name = name;
    o->opts[o->n_opts].has_arg = has_arg;
    o->opts[o->n_opts].val = val;
    o->n_opts++;
    
    return CCONF_ERROR_NO_ERROR;
}

int cconf_optlist_parse(cconf_optlist_t * o, int argc, char ** argv)
{
	char ch;
    int ix = 0;
    int ret = 0;
    
    while ((ch = getopt_long_only(argc, argv, "", o->opts, &ix)) != -1) 
    {
		if (!o->handler_fcn)
			break;
				
		ret = o->handler_fcn((int) ch, o->opts[ix].name, optarg, o->data);
		
		if (ret != 0)
			break;
    }
    
	return ret;
}

